<template>
  <div class="tabs">
    <div class="router-tabs" :class="{ 'has-button': hasButton }">
      <div class="tabs-scroll" ref="tabsRef">
        <ul class="tabs-warpper" ref="warpperRef">
          <transition-group name="tabtranslate">
            <li
              class="tab-card"
              :data-name="item.name"
              :key="item.name"
              v-for="item in tabs"
              :class="{ active: active === item.name }"
              @click="tabClick(item.name)">
              <component :is="getIcon(item.name)" class="mr-4" />
              <span>
                {{ item.title }}
              </span>
              <span class="icon" @click.stop="deleteTab(item.name)" v-if="tabs.length > 1">
                <CloseSmall />
              </span>
            </li>
          </transition-group>
        </ul>
      </div>
      <div class="button left" @click="scrollTo(-1)" v-if="hasButton">
        <Left />
      </div>
      <div class="button right" @click="scrollTo(1)" v-if="hasButton">
        <Right />
      </div>
    </div>
    <div class="tools">
      <el-button size="small" type="primary" :icon="Clear" @click="clearTab">清空</el-button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { nextTick, onMounted, ref, watch } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { Left, Right, Clear, CloseSmall } from '@icon-park/vue-next';
import { useResize, useTabList } from '@/hooks';

defineOptions({
  name: 'tabList'
});

const route = useRoute();
const router = useRouter();
const tabsRef = ref();
const hasButton = ref(false);
const warpperRef = ref();
//这里的tablist并不是由pinia构建的，只是普通的钩子
//如果需要在其它页面实时监听tabs的变化，请自行重构该函数并使用pinia来管理tabs
const { tabs, addTabItem, removeTabItem, clearTabs, getIcon } = useTabList();
const active = ref<string>('');

function addTab(item) {
  addTabItem(item);
  changeActive(item.name);
}

function changeActive(name: any) {
  active.value = name;
}

function deleteTab(name) {
  let idx = removeTabItem(name);

  if (active.value === name) {
    idx === tabs.value.length && idx--;
    tabClick(tabs.value[idx].name);
  }
}

function tabClick(name) {
  router.push({ name });
  _scrollIntoView(name);
}

function _scrollIntoView(name: string) {
  let dom: HTMLElement = warpperRef.value?.querySelector(`li[data-name="${name}"]`);
  tabsRef.value.scrollLeft = dom.offsetLeft - tabsRef.value.offsetWidth / 2;
}

function clearTab() {
  let current = tabs.value.find((v) => v.name === active.value);
  clearTabs(current);
}

function resize() {
  hasButton.value = tabsRef.value?.scrollWidth > tabsRef.value?.offsetWidth;
}

function scrollTo(value: number) {
  let scrollLeft = tabsRef.value.scrollLeft + tabsRef.value.offsetWidth * value;
  tabsRef.value.scrollTo({
    left: scrollLeft,
    behavior: 'smooth'
  });
}

watch(
  () => tabs.value.length,
  () => {
    resize();
  }
);

watch(
  () => route.name,
  () => {
    const { name, path, meta } = route;
    if (tabs.value.find((v) => v.name === name)) {
      changeActive(name);
    } else {
      addTab({
        name,
        path,
        title: meta.title
      });
    }
  },
  {
    immediate: true
  }
);

useResize(tabsRef, resize, { debounce: 200 });

onMounted(() => {
  resize();
});
</script>

<style scoped lang="scss">
.tabs {
  width: 100%;
  display: flex;
  height: 100%;
  align-items: center;
  flex-wrap: nowrap;
  position: relative;

  .tools {
    display: flex;
    align-items: center;
    padding-right: 10px;
  }
}
.router-tabs {
  position: relative;
  display: flex;
  flex: auto;
  flex-wrap: nowrap;
  height: 100%;
  transition: padding 200ms;

  .tabs-scroll {
    padding: 0 10px;
    flex: 1;
    width: 0;
    display: flex;
    overflow-x: auto;
    scrollbar-width: none;
    scroll-behavior: smooth;
  }

  .tabs-warpper {
    display: inline-flex;
    align-items: flex-end;
    white-space: nowrap;
    position: relative;
    z-index: 1;
    // gap: 8px;

    .tab-card {
      --record-size: 15px;
      --record-bg: transparent;

      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 0 15px;
      min-width: 100px;
      height: 30px;
      font-size: 14px;
      line-height: 1;
      position: relative;
      background-color: var(--record-bg);
      border-radius: 18px 18px 0 0;

      cursor: pointer;
      user-select: none;

      &::before,
      &::after {
        content: '';
        display: none;
        position: absolute;
        width: var(--record-size);
        height: var(--record-size);
        bottom: 0;
      }

      &::before {
        left: calc(0px - var(--record-size));
        background: radial-gradient(
          circle at 0 0,
          transparent var(--record-size),
          var(--record-bg) calc(var(--record-size) + 1px)
        );
      }

      &::after {
        right: calc(0px - var(--record-size));
        background: radial-gradient(
          circle at var(--record-size) 0,
          transparent var(--record-size),
          var(--record-bg) calc(var(--record-size) + 1px)
        );
      }

      .icon {
        margin-left: 4px;
        display: flex;
        color: var(--el-text-color-secondary);
      }

      &:hover {
        color: var(--el-color-primary);
        .icon:hover {
          color: var(--el-color-primary);
        }
      }
    }
    .tab-card.active {
      --record-bg: #eeeeee;
      color: var(--el-color-primary);

      &::before,
      &::after {
        display: block;
      }
    }
  }

  .button {
    position: absolute;
    top: 50%;
    transform: translate(0, -50%);
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    width: 30px;
    z-index: 2;
    cursor: pointer;

    .i-icon {
      display: flex;
    }

    &:hover {
      color: var(--el-color-primary);
    }
  }
  .button.left {
    left: 0;
    box-shadow: 5px 0 5px -4px #0000004d;
  }
  .button.right {
    right: 0;
    box-shadow: -5px 0 5px -4px #0000004d;
  }
}
.router-tabs.has-button {
  padding: 0 30px;

  .tabs-scroll {
    overflow-x: auto;
    scrollbar-width: none;
  }

  .tabs-scroll::-webkit-scrollbar {
    display: none;
  }
}
.tabtranslate-enter-active,
.tabtranslate-leave-active {
  transition: all 200ms ease;
}

.tabtranslate-enter-from,
.tabtranslate-leave-to {
  transform: translateY(100%);
  opacity: 0;
}
</style>
